package xyz.xpman.prisonerfitness.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import org.jetbrains.annotations.NotNull;

import java.util.function.IntConsumer;

import xyz.xpman.prisonerfitness.R;
import xyz.xpman.prisonerfitness.util.DisplayUtils;

@SuppressWarnings("unused")
public class CountdownRoundView extends View {
    public static final int defaultColorId = R.color.colorAccent;
    public static final String COUNTDOWN_TIME_FLAG = "${countdownTime}";

    // 圆轮颜色、宽度、文本大小
    private final int ringColor;
    private final float ringWidth;

    private final ITextReplaceCatch progressTextRender;

    private final int progressTextColor;
    private final int ringProgressTextSize;
    private final Paint paint;
    // 圆环的矩形区域
    private RectF rectF;
    private float currentProgress;
    private ValueAnimator valueAnimator = null;

    private final int countdownTime;
    private int countdownValue;
    private long duration = 1000L;

    private IntConsumer countdownListener = (i) -> { };
    private OnCountDownFinishListener countdownFinishListener = () -> {};

    private String progressText = "";


    public CountdownRoundView(@NotNull Context context) {
        this(context, null);
    }

    public CountdownRoundView(@NotNull Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * 默认属性：
     *      CountdownRoundView_ringColor 颜色
     *      CountdownRoundView_ringWidth 宽度
     *      CountdownRoundView_progressTextSize  文字大小
     *      CountdownRoundView_progressTextColor 文字颜色
     *      CountdownRoundView_countdownTime 倒计时时间
     */
    public CountdownRoundView(@NotNull Context context, @NotNull AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        @SuppressLint("CustomViewStyleable")
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CountdownRoundView);
        ringColor = a.getColor(R.styleable.CountdownRoundView_ringColor, context.getResources().getColor(defaultColorId));
        ringWidth = a.getInt(R.styleable.CountdownRoundView_ringWidth, 40);
        final String progressTextFmt = a.getString(R.styleable.CountdownRoundView_progressTextFmt);
        progressTextColor = a.getColor(R.styleable.CountdownRoundView_progressTextColor, context.getResources().getColor(defaultColorId));
        ringProgressTextSize = a.getDimensionPixelSize(R.styleable.CountdownRoundView_progressTextSize, DisplayUtils.sp2px(context, 20));
        countdownTime = a.getInteger(R.styleable.CountdownRoundView_countdownTime, 60);

        countdownValue = countdownTime;
        progressTextRender = ITextReplaceCatch.by(progressTextFmt, COUNTDOWN_TIME_FLAG);

        a.recycle();
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setAntiAlias(true);
        this.setWillNotDraw(false);
    }




    @SuppressLint("DrawAllocation")
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //宽度
        int mWidth = getMeasuredWidth();
        //高度
        int mHeight = getMeasuredHeight();

        float temp = ringWidth / 2;
        rectF = new RectF(0 + temp, 0 + temp,
                mWidth - temp, mHeight - temp);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 圆环
        //颜色
        paint.setColor(ringColor);
        //空心
        paint.setStyle(Paint.Style.STROKE);
        //宽度
        paint.setStrokeWidth(ringWidth);
        canvas.drawArc(rectF, -90, currentProgress - 360, false, paint);
        //绘制文本
        @SuppressLint("DrawAllocation")
        final Paint textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(ringProgressTextSize);
        textPaint.setColor(progressTextColor);

        // 文字居中显示
        final Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
        final int baseline = (int) ((rectF.bottom + rectF.top - fontMetrics.bottom - fontMetrics.top) / 2);

        canvas.drawText(progressText, rectF.centerX(), baseline, textPaint);
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private interface ITextReplaceCatch {

        String render(@NotNull final String replacement);


        static ITextReplaceCatch by(final String text,
                                    final String target) {
            if (null == text) {
                return replacement -> null;
            }

            if (null == target) {
                return replacement -> text;
            }



            final int startIndex = text.indexOf(target);

            if (-1 == startIndex) {
                return replacement -> text;
            }
            return new TextReplaceCatch(text.replace(target, ""), startIndex);
        }

    }

    private static class TextReplaceCatch implements ITextReplaceCatch {
        private final String text;
        private final int startIndex;

        public TextReplaceCatch(@NotNull String text, int startIndex) {
            this.text = text;
            this.startIndex = startIndex;
        }

        @Override
        public String render(@NotNull String replacement) {
            return text.substring(0, startIndex)
                    + replacement
                    + text.substring(startIndex);
        }
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    public void setDuration(long duration) {
        this.duration = duration;
    }


    public void setCountdownListener(IntConsumer listener) {
        if (null != listener) {
            this.countdownListener = listener;
        }
    }


    public void setCountdownFinishedListener(OnCountDownFinishListener listener) {
        if (null != listener) {
            this.countdownFinishListener = listener;
        }
    }

    public void requireCountdownFinished() {
        countdownFinishListener.countDownFinished();
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private ValueAnimator newValueAnimator(int maxValue) {
        return newValueAnimator(maxValue, maxValue * duration);
    }

    /**
     * 生成ValueAnimator
     * @param maxValue 最大值
     * @param duration duration(单位：毫秒)
     * @return ValueAnimator
     */
    private ValueAnimator newValueAnimator(int maxValue, long duration) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, maxValue);
        valueAnimator.setDuration(duration);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setRepeatCount(0);
        return valueAnimator;
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    /**
     * 开始倒计时
     */
    public void start() {
        valueAnimator = newValueAnimator(countdownTime);

        valueAnimator.addUpdateListener(animation -> {
            Integer animatedValue = (Integer) animation.getAnimatedValue();

            if (animatedValue != countdownValue) {
                countdownValue = animatedValue;

                final int value = countdownTime - countdownValue;
                progressText = progressTextRender.render(String.valueOf(value));

                // 去掉小数点后数字
                currentProgress = (int) (360 * (float) animatedValue / (float) countdownTime);

                countdownListener.accept(value);
                invalidate();
            }
        });

        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

                // 倒计时结束回调
                countdownFinishListener.countDownFinished();
            }
        });

        valueAnimator.resume();
        valueAnimator.start();
    }

    /**
     * 恢复倒计时（从暂停时继续开始倒计时）
     */
    public void resume() {
        valueAnimator.resume();
    }

    public void pause() {
        valueAnimator.pause();
    }

    public void stop() {
        valueAnimator.end();
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    public interface OnCountDownFinishListener {
        void countDownFinished();
    }

}
